#!/usr/bin/env python3
"""
通用工具模块

提供GitCode和GitLab平台共享的工具函数和通用逻辑。
包含数据显示、用户映射、活跃度计算等功能。
"""

from datetime import datetime, timedelta
from typing import List, Dict, Tuple

import pandas as pd
import plotly.express as px
import streamlit as st

# 导入核心工具类
from core.utils import CommonUtils as CoreUtils


class CommonUtils:
    """通用工具类"""

    @staticmethod
    def get_activity_thresholds(time_range: str) -> Tuple[int, int]:
        """根据时间周期计算活跃天数阈值"""
        return CoreUtils.get_activity_thresholds(time_range)

    @staticmethod
    def render_sidebar_config() -> Tuple[str, str, str, str, str, datetime]:
        """渲染侧边栏配置"""
        st.sidebar.title("🔧 配置")

        # 平台选择
        st.sidebar.subheader("🌐 平台选择")
        platform = st.sidebar.selectbox(
            "选择代码托管平台",
            ["GitCode", "GitLab"],
            index=0,
            help="选择要分析的代码托管平台",
            key="common_platform_select"
        )

        # 根据平台显示不同的配置
        if platform == "GitCode":
            from .gitcode_interface import GitCodeInterface
            gitcode_ui = GitCodeInterface()
            access_token, org_name = gitcode_ui.render_sidebar_config()
            gitlab_url = None
        else:  # GitLab
            # GitLab平台不需要在这里配置认证信息
            access_token = None
            gitlab_url = None
            org_name = None

        # 对于GitLab平台，不需要时间范围配置（使用物化视图）
        if platform == "GitCode":
            # 时间范围配置（仅对GitCode有效）
            st.sidebar.subheader("⏰ 时间范围")
            time_range = st.sidebar.selectbox(
                "选择分析时间范围",
                ["最近1个月", "最近3个月", "最近6个月", "最近1年"],
                index=2,  # 默认选择"最近6个月"
                key="common_time_range_select"
            )

            # 计算时间范围
            since_date = None
            if time_range == "最近1个月":
                since_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%dT%H:%M:%S')
            elif time_range == "最近3个月":
                since_date = (datetime.now() - timedelta(days=90)).strftime('%Y-%m-%dT%H:%M:%S')
            elif time_range == "最近6个月":
                since_date = (datetime.now() - timedelta(days=180)).strftime('%Y-%m-%dT%H:%M:%S')
            elif time_range == "最近1年":
                since_date = (datetime.now() - timedelta(days=365)).strftime('%Y-%m-%dT%H:%M:%S')
        else:
            # GitLab平台使用物化视图，不需要动态时间范围
            time_range = "物化视图数据"
            since_date = None

        return access_token, org_name, since_date, time_range, platform, gitlab_url

    @staticmethod
    def display_repo_overview(df: pd.DataFrame, platform: str = "GitCode"):
        """显示仓库概览"""
        CoreUtils.display_repo_overview(df, platform)

    @staticmethod
    def display_commits_analysis(df: pd.DataFrame, repo_name: str, platform: str = "GitCode"):
        """显示提交分析"""
        CoreUtils.display_commits_analysis(df, repo_name, platform)

    @staticmethod
    def display_overall_analysis(overall_data: List[pd.DataFrame], time_range: str):
        """显示整体分析结果"""
        CoreUtils.display_overall_analysis(overall_data, time_range)

    @staticmethod
    def load_username_name_mapping() -> Dict[str, str]:
        """加载用户名姓名映射"""
        return CoreUtils.load_username_name_mapping()

    @staticmethod
    def load_user_info_mapping() -> Dict[str, Dict]:
        """加载完整的用户信息映射（包括姓名、部门、状态）"""
        return CoreUtils.load_user_info_mapping()

    @staticmethod
    def get_display_name(username: str, name_mapping: Dict[str, str]) -> str:
        """获取显示名称，优先使用映射的姓名，如果姓名为空则使用用户名"""
        return CoreUtils.get_display_name(username, name_mapping)

    @staticmethod
    def display_student_analysis(student_stats: List[Dict], time_range: str = "最近1年"):
        """显示提交者级别的详细分析"""
        if not student_stats:
            st.warning("没有找到提交者统计数据")
            return

        # 加载用户名姓名映射和完整用户信息
        username_name_mapping = CommonUtils.load_username_name_mapping()
        user_info_mapping = CommonUtils.load_user_info_mapping()

        # 获取基于时间周期的活跃度阈值
        normal_threshold, high_threshold = CommonUtils.get_activity_thresholds(time_range)

        st.subheader("👥 提交者工作量详细统计")

        # 部门活跃度综合统计图表（仅GitCode支持）
        # 检查是否为GitCode平台（通过检查数据结构中是否包含GitCode特有字段）
        if student_stats and len(student_stats) > 0:
            first_student = student_stats[0]
            # GitCode数据包含total_add_lines和total_delete_lines字段
            if 'total_add_lines' in first_student and 'total_delete_lines' in first_student:
                CommonUtils._display_department_activity_chart(student_stats, username_name_mapping, user_info_mapping)

        # 总体统计指标
        col1, col2, col3, col4 = st.columns(4)

        total_students = len(student_stats)
        total_commits = sum(s['total_commits'] for s in student_stats)
        total_add_lines = sum(s['total_add_lines'] for s in student_stats)
        total_delete_lines = sum(s['total_delete_lines'] for s in student_stats)

        with col1:
            st.metric("提交者总数", total_students)

        with col2:
            st.metric("总提交数", f"{total_commits:,}")

        with col3:
            st.metric("总新增行数", f"{total_add_lines:,}")

        with col4:
            st.metric("总删除行数", f"{total_delete_lines:,}")

        # 提交数分布图
        commits_data = [s['total_commits'] for s in student_stats[:20]]
        names_data = [CommonUtils.get_display_name(s['user_name'], username_name_mapping) for s in student_stats[:20]]

        fig = px.bar(
            x=commits_data,
            y=names_data,
            orientation='h',
            title="Top 20 提交者总提交数排行",
            labels={'x': '总提交数', 'y': '提交者'}
        )
        fig.update_layout(height=500)
        st.plotly_chart(fig, use_container_width=True)

        # 代码行数排行榜
        st.subheader("📝 代码贡献排行榜 (Top 20)")

        # 创建两列布局显示新增和删除行数图表
        col1, col2 = st.columns(2)

        with col1:
            # 新增代码行数分布图
            add_lines_data = [s['total_add_lines'] for s in student_stats[:20]]

            fig = px.bar(
                x=add_lines_data,
                y=names_data,
                orientation='h',
                title="Top 20 提交者总新增代码行数排行",
                labels={'x': '总新增代码行数', 'y': '提交者'},
                color=add_lines_data,
                color_continuous_scale='Greens'
            )
            fig.update_layout(height=500)
            st.plotly_chart(fig, use_container_width=True)

        with col2:
            # 删除代码行数分布图
            delete_lines_data = [s['total_delete_lines'] for s in student_stats[:20]]

            fig = px.bar(
                x=delete_lines_data,
                y=names_data,
                orientation='h',
                title="Top 20 提交者总删除代码行数排行",
                labels={'x': '总删除代码行数', 'y': '提交者'},
                color=delete_lines_data,
                color_continuous_scale='Reds'
            )
            fig.update_layout(height=500)
            st.plotly_chart(fig, use_container_width=True)

        # 总修改行数（新增+删除）排行榜
        st.subheader("🔄 总代码修改量排行榜 (Top 20)")

        total_changes_data = [s['total_add_lines'] + s['total_delete_lines'] for s in student_stats[:20]]

        fig = px.bar(
            x=total_changes_data,
            y=names_data,
            orientation='h',
            title="Top 20 提交者总代码修改量排行（新增+删除）",
            labels={'x': '总修改行数', 'y': '提交者'},
            color=total_changes_data,
            color_continuous_scale='Blues'
        )
        fig.update_layout(height=500)
        st.plotly_chart(fig, use_container_width=True)

        # 提交者活跃度分析
        st.subheader("📈 提交者活跃度分析")

        # 活跃度分布图表
        active_days_data = [s.get('active_days', 0) for s in student_stats[:20]]

        # 创建活跃度分布图
        fig = px.bar(
            x=active_days_data,
            y=names_data,
            orientation='h',
            title="Top 20 提交者活跃天数排行",
            labels={'x': '活跃天数', 'y': '提交者'},
            color=active_days_data,
            color_continuous_scale='Viridis'
        )

        # 添加阈值线
        fig.add_vline(x=normal_threshold, line_dash="dash", line_color="orange",
                      annotation_text=f"正常阈值({normal_threshold}天)")
        fig.add_vline(x=high_threshold, line_dash="dash", line_color="green",
                      annotation_text=f"高活跃阈值({high_threshold}天)")

        fig.update_layout(height=500)
        st.plotly_chart(fig, use_container_width=True)

        # 活跃度统计概览
        high_active = len([s for s in student_stats if s.get('active_days', 0) > high_threshold])
        normal_active = len([s for s in student_stats if normal_threshold < s.get('active_days', 0) <= high_threshold])
        low_active = len([s for s in student_stats if s.get('active_days', 0) <= normal_threshold])

        col1, col2, col3 = st.columns(3)
        with col1:
            st.metric("🔥 高活跃度", high_active, f">{high_threshold}天")
        with col2:
            st.metric("✅ 正常活跃", normal_active, f"{normal_threshold + 1}-{high_threshold}天")
        with col3:
            st.metric("⚠️ 低活跃度", low_active, f"≤{normal_threshold}天")

        # 找出低活跃度提交者（活跃天数 <= normal_threshold），排除部门为"外协"和在职状态为"离职"的用户
        low_activity_students = []
        for s in student_stats:
            if s.get('active_days', 0) <= normal_threshold:
                user_info = user_info_mapping.get(s['user_name'], {})
                department = user_info.get('department', '')
                status = user_info.get('status', '')
                if department != '外协' and status != '离职':
                    low_activity_students.append(s)

        if low_activity_students:
            st.error(
                f"⚠️ 发现 {len(low_activity_students)} 名提交者活跃度较低（活跃天数 ≤ {normal_threshold}，年化<60天）")

            low_activity_data = []
            for student in low_activity_students:
                display_name = CommonUtils.get_display_name(student['user_name'], username_name_mapping)
                user_info = user_info_mapping.get(student['user_name'], {})
                low_activity_data.append({
                    "提交者姓名": display_name,
                    "用户名": student['user_name'],
                    "部门": user_info.get('department', '未知部门'),
                    "在职状态": user_info.get('status', ''),
                    "总提交数": student['total_commits'],
                    "近期活跃天数": student.get('active_days', 0),
                    "最后活跃时间": student.get('last_active_time', ''),
                    "总新增代码行数": student['total_add_lines'],
                    "涉及仓库数": student['repos_involved'],
                    "状态": "🔴 需要关注"
                })

            low_activity_df = pd.DataFrame(low_activity_data)
            st.dataframe(low_activity_df, use_container_width=True, hide_index=True)
        else:
            st.success("✅ 所有提交者活跃度正常")

        # 详细统计表格
        st.subheader("📋 详细统计表格")

        detailed_data = []
        rank = 1
        for student in student_stats:
            display_name = CommonUtils.get_display_name(student['user_name'], username_name_mapping)
            user_info = user_info_mapping.get(student['user_name'], {})
            department = user_info.get('department', '未知部门')
            status = user_info.get('status', '')
            
            # 过滤掉部门为"外协"和在职状态为"离职"的用户
            if department == '外协' or status == '离职':
                continue
                
            detailed_data.append({
                "排名": rank,
                "提交者姓名": display_name,
                "用户名": student['user_name'],
                "部门": department,
                "状态": status,
                "总提交数": student['total_commits'],
                "🔥月均提交次数": f"{student.get('annual_commit_rate', 0.0):.1f}",  # 关键统计指标，显著标识
                "近期活跃天数": student.get('active_days', 0),
                "最后活跃时间": student.get('last_active_time', ''),
                "总新增行数": student['total_add_lines'],
                "总删除行数": student['total_delete_lines'],
                "涉及仓库数": student['repos_involved']
            })
            rank += 1

        detailed_df = pd.DataFrame(detailed_data)
        st.dataframe(detailed_df, use_container_width=True, hide_index=True)

    @staticmethod
    def _display_department_activity_chart(student_stats, username_name_mapping, user_info_mapping):
        """显示部门活跃度综合统计图表"""
        if not student_stats:
            st.warning("暂无提交者统计数据")
            return

        # 按部门聚合数据，排除外协部门
        department_stats = {}
        for student in student_stats:
            username = student.get('user_name', '')
            user_info = user_info_mapping.get(username, {})
            department = user_info.get('department', '未知部门')
            status = user_info.get('status', '')
            
            # 跳过外协部门和离职人员
            if department == '外协' or status == '离职':
                continue

            if department not in department_stats:
                department_stats[department] = {
                    'total_commits': 0,
                    'total_additions': 0,
                    'total_deletions': 0,
                    'total_changes': 0,
                    'members': []
                }

            name = username_name_mapping.get(username, username)
            total_lines = student.get('total_add_lines', 0) + student.get('total_delete_lines', 0)

            department_stats[department]['total_commits'] += student.get('total_commits', 0)
            department_stats[department]['total_additions'] += student.get('total_add_lines', 0)
            department_stats[department]['total_deletions'] += student.get('total_delete_lines', 0)
            department_stats[department]['total_changes'] += total_lines
            department_stats[department]['members'].append({
                'name': name,
                'username': username,
                'total_lines': total_lines,
                'total_commits': student.get('total_commits', 0),
                'active_days': student.get('active_days', 0)
            })

        if not department_stats:
            st.warning("暂无部门统计数据")
            return

        st.subheader("🏢 部门活跃度综合统计")

        # 部门代码活跃度柱状图
        dept_names = list(department_stats.keys())
        dept_changes = [department_stats[dept]['total_changes'] for dept in dept_names]

        fig_bar = px.bar(
            x=dept_names,
            y=dept_changes,
            title="各部门代码修改总量",
            labels={'x': '部门', 'y': '代码修改行数'},
            color=dept_changes,
            color_continuous_scale='Blues'
        )
        fig_bar.update_layout(height=400, showlegend=False)
        st.plotly_chart(fig_bar, use_container_width=True)

        # 部门活跃度饼图
        fig_pie = px.pie(
            values=dept_changes,
            names=dept_names,
            title="部门代码贡献占比"
        )
        fig_pie.update_layout(height=400)
        st.plotly_chart(fig_pie, use_container_width=True)

        # 部门详细统计表格
        dept_table_data = []
        for dept_name, dept_data in department_stats.items():
            # 筛选在职员工（排除已离职员工）
            active_members = []
            for member in dept_data['members']:
                username = member.get('username', '')
                user_info = user_info_mapping.get(username, {})
                status = user_info.get('status', '').strip()
                # 只包含在职员工（状态为空或包含"在职"的员工）
                if not status or '在职' in status or status == '在职':
                    active_members.append(member)

            # 从在职员工中找最低活跃成员（按提交数量）
            min_member_by_commits = min(active_members, key=lambda x: x['total_commits']) if active_members else None
            # 从在职员工中找最低活跃成员（按活跃天数）
            min_member_by_days = min(active_members, key=lambda x: x['active_days']) if active_members else None

            dept_table_data.append({
                '部门': dept_name,
                '成员数量': len(dept_data['members']),
                '在职成员数': len(active_members),
                '总提交数': dept_data['total_commits'],
                '总代码行数': dept_data['total_changes'],
                '最低提交成员': min_member_by_commits['name'] if min_member_by_commits else 'N/A',
                '最低提交数': min_member_by_commits['total_commits'] if min_member_by_commits else 0,
                '最低活跃成员': min_member_by_days['name'] if min_member_by_days else 'N/A',
                '最低活跃天数': min_member_by_days['active_days'] if min_member_by_days else 0
            })

        dept_df = pd.DataFrame(dept_table_data)
        dept_df = dept_df.sort_values('总代码行数', ascending=False)
        st.dataframe(dept_df, use_container_width=True)

    @staticmethod
    def render_custom_css():
        """渲染自定义CSS样式"""
        st.markdown("""
        <style>
        .main-header {
            font-size: 2.5rem;
            color: #1f77b4;
            text-align: center;
            margin-bottom: 2rem;
        }
        .metric-card {
            background-color: #f0f2f6;
            padding: 1rem;
            border-radius: 0.5rem;
            margin: 0.5rem 0;
        }
        .stAlert {
            margin-top: 1rem;
        }
        .gitlab-timescale {
            border-left: 4px solid #fc6d26;
            padding-left: 1rem;
            background-color: #fef7f0;
        }
        .gitcode-legacy {
            border-left: 4px solid #1f77b4;
            padding-left: 1rem;
            background-color: #f0f7ff;
        }
        </style>
        """, unsafe_allow_html=True)
